﻿using System;
using System.Text;
using System.Threading;
using ZerAx.Net;

namespace BlockOS.Server
{
    public class ServerLocalProxy
    {
        private InterThreadConnection conn;
        private Thread serverThread;

        private bool serverRunning;

        public Action<string> onReceiveMessage;

        public void Start(ServerConfig config, Action<GameServer> initializer)
        {
            if (serverRunning) return;

            var (localConn, serverConn) = InterThreadConnection.CreatePair();

            conn = localConn;

            var server = new GameServer(serverConn, config);

            initializer?.Invoke(server);

            serverThread = new Thread(ServerRun);
            serverThread.Start(server);

            serverRunning = true;
        }

        public void Update()
        {
            if (!serverRunning) return;

            conn.Update();
            while (conn.Poll(out var packet))
            {
                switch ((ServerControlProtocolId)packet.typeId)
                {
                    case ServerControlProtocolId.RESPONSE_STOP:
                        serverRunning = false;
                        onReceiveMessage?.Invoke("Server Stopped");
                        break;

                    case ServerControlProtocolId.LOG:
                        onReceiveMessage?.Invoke(packet.ReadData(r => r.ReadString()));
                        break;

                    case ServerControlProtocolId.RESPONSE_TCP_LISTEN:
                        onReceiveMessage?.Invoke(packet.ReadData(r => r.ReadString()));
                        break;
                    default: break;
                }
            }
        }

        public void RequestStop()
        {
            if (!serverRunning) return;

            conn.Send(new Packet((byte)ServerControlProtocolId.REQUEST_STOP));
        }

        public void StartTcp(int port)
        {
            if (!serverRunning) return;

            conn.Send(new Packet((byte)ServerControlProtocolId.REQUEST_TCP_LISTEN).WriteData(w => w.Write(port)));
        }

        private static void ServerRun(object server)
        {
            ((GameServer)server).Run();
        }
    }
}
